/* Copyright © Worklight Ltd. 2006-2011.  All rights reserved. */

package com.worklight.androidgap.plugin;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

import org.json.JSONArray;
import org.json.JSONObject;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;

import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import com.worklight.androidgap.WLAndroidUtils;

public class NetworkDetector extends Plugin{
	
	@Override
	public PluginResult execute(String action, JSONArray args, String callbackId) {
		if (action.equals("getNetworkInfo")){			
			JSONObject networkInfo = getNetworkData(this.ctx);
			PluginResult result = new PluginResult(PluginResult.Status.OK, networkInfo);
			return result;
		}
		return new PluginResult(PluginResult.Status.INVALID_ACTION);
	}

	public JSONObject getNetworkData(Context ctx){
		JSONObject response = new JSONObject();
		try {
			String isNetworkConnected = "false";
			String isAirplaneMode = "false";
			String isRoaming = "false";		
			String networkConnectionTypeName = "";
			String wifiName = "";
	        String telephonyNetworkType = "";
	        String carrierName = "";
	        
	        // -------------------------------------- Network detection ------------------------------------
			ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo ni = cm.getActiveNetworkInfo();
			
			if (null != ni){ 
				isNetworkConnected = Boolean.valueOf(ni.isConnected()).toString();
				isRoaming = Boolean.valueOf(ni.isRoaming()).toString();
				networkConnectionTypeName = ni.getTypeName();
				try {
					WifiManager wifiManager = (WifiManager)ctx.getSystemService(Context.WIFI_SERVICE);
					wifiName = wifiManager.getConnectionInfo().getSSID();
				} catch (Exception e) {
					WLAndroidUtils.error("Cannot retrive WIFI info, check application permission ACCESS_WIFI_STATE in AndroidManifest.xml.", e);
				}
			}
			
	        // -------------------------------------- Telephony detection ------------------------------------
			TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
	        switch (tm.getNetworkType()){
	        case TelephonyManager.NETWORK_TYPE_1xRTT:
	    		telephonyNetworkType = "1xRTT"; break;
	    	case TelephonyManager.NETWORK_TYPE_CDMA:
	    		telephonyNetworkType = "CDMA"; break;
	    	case TelephonyManager.NETWORK_TYPE_EDGE:
	    		telephonyNetworkType = "EDGE"; break;
	    	case TelephonyManager.NETWORK_TYPE_EVDO_0:
	    		telephonyNetworkType = "EVDO_0"; break;
	    	case TelephonyManager.NETWORK_TYPE_EVDO_A:
	    		telephonyNetworkType = "EVDO_A"; break;
	    	case TelephonyManager.NETWORK_TYPE_GPRS:
	    		telephonyNetworkType = "GPRS"; break;
	    	case TelephonyManager.NETWORK_TYPE_UMTS:
	    		telephonyNetworkType = "UMTS"; break;
	    	case TelephonyManager.NETWORK_TYPE_UNKNOWN:
	    		telephonyNetworkType = ""; break;        		
	    	
	    	// TODO:
	    	// The constants in the following 3 cases where commented to support 
	   		// developers that still have Android projects with api level 4 (Android version 1.6).
	    	// these constants should be uncomment when packaging wl android framework into jar.
	    		
	    	case 8: //TelephonyManager.NETWORK_TYPE_HSDPA:
	    		telephonyNetworkType = "HSDPA"; break;
	    	case 10: //TelephonyManager.NETWORK_TYPE_HSPA:
	    		telephonyNetworkType = "HSPA"; break;
	    	case 9: //TelephonyManager.NETWORK_TYPE_HSUPA:
	    		telephonyNetworkType = "HSUPA"; break;        	
	    	default:
	    		telephonyNetworkType = "UNDETECTABLE"; break;
	        }
	        
	        
	        // Carrier
	        String networkOperator = tm.getNetworkOperator() == null || tm.getNetworkOperator().equals("") ? "" : "(" + tm.getNetworkOperator() + ")";
	        carrierName = tm.getNetworkOperatorName() + networkOperator;
	        
	        // Is Airplane Mode
	        isAirplaneMode = Boolean.toString(Settings.System.getInt(ctx.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0);
	        
	        // -------------------------------------- Response ------------------------------------
			response.put("isNetworkConnected", isNetworkConnected);
			response.put("isAirplaneMode", isAirplaneMode);
			response.put("isRoaming", isRoaming);
			response.put("networkConnectionType", networkConnectionTypeName);
			response.put("wifiName", wifiName);
			response.put("telephonyNetworkType", telephonyNetworkType);
			response.put("carrierName", carrierName);
			response.put("ipAddress", getLocalIpAddress());
		}catch (Exception e){
			WLAndroidUtils.error("Cannot retrive network diagnostic data: ", e);
		}
		return response;
	}
	
	/**
	 * Return the local IP address
	 * @return
	 */
	private String getLocalIpAddress() {
		String ipAddress = "";
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
				NetworkInterface intf = en.nextElement();
				for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
					InetAddress inetAddress = enumIpAddr.nextElement();
					if (!inetAddress.isLoopbackAddress()) {
						ipAddress = inetAddress.getHostAddress().toString();
					}
				}
				}
		} catch (SocketException ex) {
			WLAndroidUtils.error(ex.toString());
		}
		return ipAddress;
	}
}
